﻿using System;
using System.Collections.Generic;
using System.Text;
using llAma.Interface;
using llAma;
using MySql.Data.MySqlClient;

namespace socialdeveloperBackend
{
    public class SDGPC : IGpc
    {

        //In this class, we cache permissions, Permission keys = (gpcName + ":" + gpcPermissionName).ToLower();
        //ServerCache<string, PermissionRule> mGpcCache = new ServerCache<string, PermissionRule>(new TimeSpan(0, 2, 0));
        ServerCache<int, PermissionRuleSet> mGpcCache = new ServerCache<int, PermissionRuleSet>(new TimeSpan(0, 0, 30));
        ServerCache<string, int> translationCache = new ServerCache<string, int>(new TimeSpan(0, 0, 30));
        ServerCache<int, string> GPCSymbols = new ServerCache<int, string>(new TimeSpan(0, 0, 30));

        private int GetGPCIDFromName(string name)
        {
            return translationCache.GetCacheObject(name.ToLower(), delegate(string notused)
            {
                using (MySqlConnection conn = SDBackend.CreateConnection())
                {
                    using (MySqlDataReader dr = SDBackend.ExecuteReader(conn, "SELECT * FROM tbl_gpcnames WHERE name = @name",
                        new MySqlParameter("@name", name)))
                    {
                        if (dr.Read())
                        {
                            return (int)dr["id"];
                        }
                        else
                            return -2;
                    }
                }
            });
        }
        public string GetSymbol(int gpcid)
        {
            return GPCSymbols.GetCacheObject(gpcid, delegate(int k)
            {
                using (MySqlConnection conn = SDBackend.CreateConnection())
                {
                    using (MySqlDataReader r = SDBackend.ExecuteReader(conn, "SELECT * FROM tbl_gpcnames WHERE id = @id", new MySqlParameter("@id", k)))
                    {
                        if (!r.Read())
                            return new CacheEntry<string>("-");
                        else
                            return new CacheEntry<string>((string)r["symbol"]);
                    }
                }
            });
        }
        private PermissionRuleSet GetGPCRules(int id)
        {

            return mGpcCache.GetCacheObject(id);
        }
        private PermissionRuleSet defaultPrivs;
        public SDGPC()
        {
            mGpcCache.CacheMiss = delegate(int id)
            {
                if (id < 0 && defaultPrivs != null)
                    throw new InvalidOperationException("Default privs are meant to be looked up internally, and are added to any GPC looked up afterwards.");
                PermissionRuleSet rules = new PermissionRuleSet();
                if (id != -1 && id != -2)
                {
                    //Shit, This will cause a deadlock.
                    //PermissionRuleSet baseRules = GetGPCRules(-1);
                    //Copy from default privs.
                    foreach (PermissionRule p in defaultPrivs)
                    {
                        rules[p.Name] = p;
                    }
                }
                using (MySqlConnection conn = SDBackend.CreateConnection())
                {
                    using (MySqlDataReader dr = SDBackend.ExecuteReader(conn,
                        "SELECT * FROM tbl_gpc_permissions WHERE gpc_id = @gpcid",
                        new MySqlParameter("@gpcid", id)))
                    {

                        while (dr.Read())
                        {
                            PermissionRule tmp = new PermissionRule((string)dr["name"], (int)dr["value"]);
                            rules[tmp.Name] = tmp;
                        }
                    }
                }
                return rules;
            };
            //Load defaults. then wipe cache, this wont be requested again.
            defaultPrivs = mGpcCache.GetCacheObject(-1);
            mGpcCache.WipeCache();
        }
        private PermissionRule GetSingleRule(int id, string gpcPermissionName)
        {
            return mGpcCache.GetCacheObject(id)[gpcPermissionName];
        }

        bool Demand(PermissionRule r, string gpcName)
        {
            return Demand(r, GetGPCIDFromName(gpcName));
        }

        bool Demand(PermissionRule r, int gpcId)
        {
            return mGpcCache[gpcId].Demand(r);
        }

        PermissionRuleSet getPermissions(string gpcName)
        {
            return getPermissions(GetGPCIDFromName(gpcName));
        }

        PermissionRuleSet getPermissions(int gpcId)
        {
            return mGpcCache[gpcId];
        }

        bool IGpc.Demand(PermissionRule r, string gpcName)
        {
            return this.Demand(r, gpcName);
        }

        bool IGpc.Demand(PermissionRule r, int gpcId)
        {
            return this.Demand(r, gpcId);
        }

        PermissionRuleSet IGpc.getPermissions(string gpcName)
        {
            return this.getPermissions(gpcName);
        }

        PermissionRuleSet IGpc.getPermissions(int gpcId)
        {
            return this.getPermissions(gpcId);
        }


        string IGpc.GetGPCSymbol(string name)
        {
            return this.GetSymbol(GetGPCIDFromName(name));
        }

        string IGpc.GetGPCSymbol(int id)
        {
            return this.GetSymbol(id);
        }
    }
}
